package cn.yuanqiao.common.utils;

import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import cn.yuanqiao.common.constant.SysContants;
import cn.yuanqiao.common.constant.TokenConstants;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.PatternMatchUtils;
import cn.yuanqiao.common.constant.Constants;
import cn.yuanqiao.common.constant.HttpStatus;
import cn.yuanqiao.common.core.domain.entity.SysRole;
import cn.yuanqiao.common.core.domain.model.LoginUser;
import cn.yuanqiao.common.exception.ServiceException;

import javax.servlet.http.HttpServletRequest;

/**
 * 安全服务工具类
 *
 * @author ruoyi
 */
public class SecurityUtils
{
    protected static final Logger logger = LoggerFactory.getLogger(SecurityUtils.class);

    private static final String BCRYPT_PATTERN = "^\\$2a\\$|\\$2y\\$|\\$2b\\$";

    /**
     * 用户ID
     **/
    public static Long getUserId()
    {
        try
        {
            return getLoginUser().getUserId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
        }
    }

    /**
     * 获取部门ID
     **/
    public static Long getDeptId()
    {
        try
        {
            return getLoginUser().getDeptId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
        }
    }

    /**
     * 获取用户账户
     **/
    public static String getUsername()
    {
        try
        {
            return getLoginUser().getUsername();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
    }

    /**
     * 获取用户
     **/
    public static LoginUser getLoginUser()
    {
        try
        {
            return (LoginUser) getAuthentication().getPrincipal();
        }
        catch (Exception e)
        {
            //logger.error(e.getMessage(),e);
            return null;
            //throw new ServiceException("获取用户租户代码异常", HttpStatus.UNAUTHORIZED);
        }
    }

    public static String getTenantCode()
    {
        try
        {
            return getLoginUser().getUser().getTenantCode();
        }
        catch (Exception e)
        {
            logger.error(e.getMessage(),e);
            return "";
            //throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
        }
    }

    /**
     * 获取Authentication
     */
    public static Authentication getAuthentication()
    {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    /**
     * 生成BCryptPasswordEncoder密码
     *
     * @param password 密码
     * @return 加密字符串
     */
    public static String encryptPassword(String password,String encryption)
    {
        if("MD5".equals(encryption)){
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            return passwordEncoder.encode(password);
        }else if("SM3".equals(encryption)){
            return Sm3EncryptText(password);
        }
        return null;
    }

    /**
     * 判断密码是否相同
     *
     * @param rawPassword 真实密码
     * @param encodedPassword 加密后字符
     * @return 结果
     */
    public static boolean matchesPassword(String rawPassword, String encodedPassword,String encryption)
    {
        if("MD5".equals(encryption)){
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            return passwordEncoder.matches(rawPassword, encodedPassword);
        }else if("SM3".equals(encryption)){
            if(encodedPassword.equals(Sm3EncryptText(rawPassword))){
                return true;
            }
        }
        return false;
    }

    public static boolean isBcrypt(String input) {
        return input.matches(BCRYPT_PATTERN);
    }

    /**
     * 是否为管理员
     *
     * @param userId 用户ID
     * @return 结果
     */
    public static boolean isAdmin(Long userId)
    {
        return userId != null && 1L == userId;
    }

    /**
     * 验证用户是否具备某权限
     *
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public static boolean hasPermi(String permission)
    {
        return hasPermi(getLoginUser().getPermissions(), permission);
    }

    /**
     * 判断是否包含权限
     *
     * @param authorities 权限列表
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public static boolean hasPermi(Collection<String> authorities, String permission)
    {
        return authorities.stream().filter(StringUtils::hasText)
                .anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
    }

    /**
     * 验证用户是否拥有某个角色
     *
     * @param role 角色标识
     * @return 用户是否具备某角色
     */
    public static boolean hasRole(String role)
    {
        List<SysRole> roleList = getLoginUser().getUser().getRoles();
        Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
        return hasRole(roles, role);
    }

    public static String getUserRoleKey()
    {
        List<SysRole> roleList = getLoginUser().getUser().getRoles();
        Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
        StringBuilder rs= new StringBuilder();
        Iterator iterator=roles.iterator();
        while(iterator.hasNext()){
            String sp=(String) iterator.next();
            rs.append(sp).append("|");
        }
        rs.deleteCharAt(rs.length()-1);
        return rs.toString();

    }


    /**
     * 判断是否包含角色
     *
     * @param roles 角色列表
     * @param role 角色
     * @return 用户是否具备某角色权限
     */
    public static boolean hasRole(Collection<String> roles, String role)
    {
        return roles.stream().filter(StringUtils::hasText)
                .anyMatch(x -> Constants.SUPER_ADMIN.equals(x.toLowerCase()) || PatternMatchUtils.simpleMatch(x.toLowerCase(), role));
    }

    /**
     * 获取请求token
     */
    public static String getToken()
    {
        return getToken(ServletUtils.getRequest());
    }

    /**
     * 根据request获取请求token
     */
    public static String getToken(HttpServletRequest request)
    {
        // 从header获取token标识
        String token = request.getHeader(TokenConstants.AUTHENTICATION);
        return replaceTokenPrefix(token);
    }

    /**
     * 裁剪token前缀
     */
    public static String replaceTokenPrefix(String token)
    {
        // 如果前端设置了令牌前缀，则裁剪掉前缀
        if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX))
        {
            token = token.replaceFirst(TokenConstants.PREFIX, "");
        }
        return token;
    }



    /**
     * 是否为三员
     *
     * @return 结果
     */
    public static boolean isSanYuan()
    {
        return isSys("_sysadmin")||isSys("_syssso")||isSys("_sysauditor");
    }

    /*public static boolean isSysAdmin(){
        return hasRole(getTenantCode().toLowerCase()+"_sysadmin");
    }

    public static boolean isSysSso(){
        return hasRole(getTenantCode().toLowerCase()+"_syssso");
    }

    public static boolean isSysAuditor(){
        return hasRole(getTenantCode().toLowerCase()+"_sysauditor");
    }*/

    public static boolean isSys(String flag){
        //TODO 判断是否系统管理员
        String[] split = getUserRoleKey().split("\\|");
        for(String s:split){
            if(SysContants.MANAGEROLEFLAG.equals(s)){
                return true;
            }
        }
        for (String item : split) {
            if (item.equals(getTenantCode()+flag)){
                return true;
            }
        }
        return false;
    }

    public static boolean isSysAdmin(){
        //TODO 判断是否系统管理员
        String[] split = getUserRoleKey().split("\\|");
        for (String item : split) {
            if (item.equals(getTenantCode()+"_sysadmin")){
                return true;
            }
        }
        return false;
    }

    public static boolean isSysSso(){
        //TODO 判断是否保密管理员
        String[] split = getUserRoleKey().split("\\|");
        for (String item : split) {
            if (item.equals(getTenantCode()+"_syssso")){
                return true;
            }
        }
        return false;
    }

    public static boolean isSysAuditor(){
        //TODO 判断是否安全审计员
        String[] split = getUserRoleKey().split("\\|");
        for (String item : split) {
            if (item.equals(getTenantCode()+"_sysauditor")){
                return true;
            }
        }
        return false;
    }

    public static boolean isDagly() {
        return hasRole("dagly");
    }

    public static String getUserType() {
        return getLoginUser().getUser().getTenantCode()==null?"manager":"user";
    }

    /**
     * SM3加密
     *
     * @param content 要加密的内容
     */
    public static String Sm3EncryptText(String content) {
        byte[] bytes = content.getBytes();
        byte[] hash = hash(bytes);
        String sm3 = ByteUtils.toHexString(hash);
        return sm3;
    }

    public static byte[] hash(byte[] srcData){
        SM3Digest digest=new SM3Digest();
        digest.update(srcData,0,srcData.length);
        byte[] bytes = new byte[digest.getDigestSize()];
        digest.doFinal(bytes,0);
        return bytes;
    }

    public static void main(String[] args) throws Exception {
        Long a = new Date().getTime();
        System.out.println(Sm3EncryptText("123456"));
        Long b = new Date().getTime();


        System.out.println("m3  " + (b - a));
    }
}
